
/**
 * 
 *  V2 版本  所有union设备都融合在一起，共用一套代码
 *          支持云端、机器人双通道控制
 *         每台互联设备还提供独立方案，对应
 * 			  fan_mqtt.c  ：可调速风扇
			* door_mqtt.c  : 开关简易门锁
			* lamb_mqtt.c  ：可调光台灯
			* water_mqtt.c  ：浇水机，附带温湿度检测、烟雾检测功能，并上报云服务器； 超过阈值报警
 * 编译记得修改 BUILD.gn
 * data:2022.06.01 HelloKun 优化
 * */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"

#include "wifi_connect.h"
#include "MQTTClient.h"

#include "wifiiot_errno.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_adc.h"
#include "wifiiot_uart.h"
#include "wifiiot_pwm.h"
#include "hi_uart.h"
#include "hi_time.h" //hi_udelay()

#include "mq2_mqtt.h"

#define UART_BUFF_SIZE 1000
#define MQTT_BUFF_SIZE 1000

static const char *data = "MRobot_fan\r\n";
uint8_t uart_buff[UART_BUFF_SIZE] = {0};
uint8_t *uart_buff_ptr = uart_buff;
char mqtt_buff[MQTT_BUFF_SIZE] = {0};
char water_union_data[30] = {0}; //互联设备中转消息

bool fan_status = false;

typedef struct
{
	float ppm_val;
	float temp_val;
	float humi_val;

} Water_Data_Typedef;

Water_Data_Typedef EnvData;

static unsigned char sendBuf[1000];
static unsigned char readBuf[1000];


Network network;

void messageArrived(MessageData *data)
{
	printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data,
		   data->message->payloadlen, data->message->payload);
	strcpy(mqtt_buff, data->message->payload);
	printf("mqtt_buff%s \n", mqtt_buff);
}

/************* MRobotUnionDevices Control ******************/
// GPIO 接口与原理图对应  使用哪个就在主函数加入Init、 Ctr函数。

static void MyUartInit(void)
{
	uint32_t ret;
	WifiIotUartAttribute uart_attr = {
		.baudRate = 115200,

		// data_bits: 8bits
		.dataBits = 8,
		.stopBits = 1,
		.parity = 0,
	};

	// Initialize uart driver
	ret = UartInit(WIFI_IOT_UART_IDX_1, &uart_attr, NULL);
	if (ret != WIFI_IOT_SUCCESS)
	{
		printf("Failed to init uart! Err code = %d\n", ret);
		return;
	}
}

/********************** Fan **************************/
static void FanInit(void)
{
	//初始化GPIO
	GpioInit();
	IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_PWM0_OUT);
	GpioSetDir(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_DIR_OUT);
	PwmInit(WIFI_IOT_PWM_PORT_PWM0);
	GpioInit();
	IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2, WIFI_IOT_IO_FUNC_GPIO_2_PWM2_OUT);
	GpioSetDir(WIFI_IOT_IO_NAME_GPIO_2, WIFI_IOT_GPIO_DIR_OUT);
	PwmInit(WIFI_IOT_PWM_PORT_PWM2); //测试接口  bearpi 板载led
}
static void FanCtr(void)
{
	//通过串口1接收MRobot2Fan data
	//UartRead(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE); // 修改timeout读取/vendor/hisi/hi3861/hi3861_adapter/hals/iot_hardware/wifiiot_lite/hal_wifiiot_uart.c
	hi_uart_read_timeout(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE, 10);
	printf("Uart1 read fan data:%s\n", uart_buff_ptr);
	if ((uart_buff[0] == '1' && uart_buff[1] == '0') || (mqtt_buff[0] == '1' && mqtt_buff[1] == '0'))
	{
		printf("******* Fan Off *****\n");
		PwmStop(WIFI_IOT_PWM_PORT_PWM0); //关闭
		PwmStop(WIFI_IOT_PWM_PORT_PWM2); //关闭
		uart_buff[0] = '5';
		mqtt_buff[0] = '5';
		fan_status = false;
		return;
	}
	if ((uart_buff[0] == '1' && uart_buff[1] == '1') || (mqtt_buff[0] == '1' && mqtt_buff[1] == '1'))
	{
		printf("******* Fan ON lev-1*****\n");
		PwmStart(WIFI_IOT_PWM_PORT_PWM0, 15000, 40000); //duty 0-65535  freq  160M/0-65535
		PwmStart(WIFI_IOT_PWM_PORT_PWM2, 15000, 40000);
		uart_buff[0] = '5';
		mqtt_buff[0] = '5';
		fan_status = true;
		return;
	}
	if ((uart_buff[0] == '1' && uart_buff[1] == '2') || (mqtt_buff[0] == '1' && mqtt_buff[1] == '2'))
	{
		printf("******* Fan ON lev-2*****\n");
		PwmStart(WIFI_IOT_PWM_PORT_PWM0, 25000, 40000); //duty 0-65535  freq  160M/0-65535
		PwmStart(WIFI_IOT_PWM_PORT_PWM2, 25000, 40000);
		uart_buff[0] = '5';
		mqtt_buff[0] = '5';
		fan_status = true;
		return;
	}
	if ((uart_buff[0] == '1' && uart_buff[1] == '3') || (mqtt_buff[0] == '1' && mqtt_buff[1] == '3'))
	{
		printf("******* Fan ON lev-3 *****\n");
		PwmStart(WIFI_IOT_PWM_PORT_PWM0, 40000, 40000); //duty 0-65535  freq  160M/0-65535
		PwmStart(WIFI_IOT_PWM_PORT_PWM2, 40000, 40000);
		uart_buff[0] = '5';
		mqtt_buff[0] = '5';
		fan_status = true;
	}
}

/********************** Door *************************/
static void DoorInit(void)
{
	//初始化GPIO
	GpioInit();
	IoSetFunc(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_IO_FUNC_GPIO_10_GPIO);
	GpioSetDir(WIFI_IOT_GPIO_IDX_10, WIFI_IOT_GPIO_DIR_OUT);
	//GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 1);
}
/* @brief  Servo  control *
 @param angle  input value: 500-2500 *
*/
void My_servo(int angle)
{
	int j = 0;
	for (j = 0; j < 10; j++)
	{
		GpioInit();
		GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 1);
		hi_udelay(angle); // angle ms
		GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 0);
		hi_udelay(20000 - angle);
	} // 20ms 控制舵机
}

static void DoorCtr(void)
{
	//UartRead(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE);
	hi_uart_read_timeout(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE, 10);
	printf("Uart1 read door data:%s \n", uart_buff_ptr);
	if (uart_buff[0] == '2' && uart_buff[1] == '1')
	{
		//模拟20ms周期 PWM  控制舵机开门
		printf("******* Open Door *****\n");
		My_servo(800); //开门
		sleep(1);
		My_servo(1500);
		uart_buff[0] = '5';
	}

	if (mqtt_buff[0] == '2' && mqtt_buff[1] == '1')
	{
		//模拟20ms周期 PWM  控制舵机开门

		printf("******* Close Door *****\n");
		My_servo(800);
		sleep(1);
		My_servo(1500);
		mqtt_buff[0] = '5';
	}

	//My_servo(180); //自动复位 模拟舵机有点迷。值是测试出来的，上面的延时<0 居然可以实现舵机控制
	printf("******* Auto reset Door *****\n");
}

/********************** Lamb **********************/
static void LambInit(void)
{
	//初始化GPIO
	GpioInit();
	IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2, WIFI_IOT_IO_FUNC_GPIO_2_PWM2_OUT);
	GpioSetDir(WIFI_IOT_IO_NAME_GPIO_2, WIFI_IOT_GPIO_DIR_OUT);
	PwmInit(WIFI_IOT_PWM_PORT_PWM2);
	PwmStart(WIFI_IOT_PWM_PORT_PWM2, 30000, 40000);
}

static void LambCtr(void)
{
	//UartRead(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE);
	hi_uart_read_timeout(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE, 10);
	printf("Uart1 read lamb data:%s \n", uart_buff_ptr);
	if ((uart_buff[0] == '3' && uart_buff[1] == '1') || (mqtt_buff[0] == '3' && mqtt_buff[1] == '1'))
	{
		printf("******* Trun On Lamb lev-1 *****\n");
		PwmStart(WIFI_IOT_PWM_PORT_PWM2, 15000, 40000);
		uart_buff[0] = '5';
		mqtt_buff[0] = '5'; //解耦 -防止两个通道互相干扰
		return;
	}
	if ((uart_buff[0] == '3' && uart_buff[1] == '2') || (mqtt_buff[0] == '3' && mqtt_buff[1] == '2'))
	{
		printf("******* Trun On Lamb lev-2*****\n");
		PwmStart(WIFI_IOT_PWM_PORT_PWM2, 25000, 40000);
		uart_buff[0] = '5';
		mqtt_buff[0] = '5';
		return;
	}
	if ((uart_buff[0] == '3' && uart_buff[1] == '3') || (mqtt_buff[0] == '3' && mqtt_buff[1] == '3'))
	{
		printf("******* Trun On Lamb lev-3 *****\n");
		PwmStart(WIFI_IOT_PWM_PORT_PWM2, 40000, 40000);
		uart_buff[0] = '5';
		mqtt_buff[0] = '5';
		return;
	}

	if ((uart_buff[0] == '3' && uart_buff[1] == '0') || (mqtt_buff[0] == '3' && mqtt_buff[1] == '0'))
	{
		printf("******* Trun Off Lamb *****\n");
		PwmStop(WIFI_IOT_PWM_PORT_PWM2);
		uart_buff[0] = '5';
		mqtt_buff[0] = '5';
	}
}

/********************** Water ***********************/
static void WaterInit(void)
{
	//初始化GPIO
	GpioInit();
	IoSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_PWM1_OUT);
	GpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_GPIO_DIR_OUT);
	PwmInit(WIFI_IOT_PWM_PORT_PWM1); //Beep Alarm

	GpioInit();
	IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_GPIO);
	GpioSetDir(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_GPIO_DIR_OUT); //water motor

	usleep(1000000);
	SensorInit();
}
static void WaterCtr(void)
{
	//UartRead(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE);
	hi_uart_read_timeout(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE, 10);
	printf("Uart1 read water data:%s \n", uart_buff_ptr);
	if (uart_buff[0] == '4' && uart_buff[1] == '1')
	{
		//PwmStart(WIFI_IOT_PWM_PORT_PWM1, 30000, 40000);
		GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 1);
		osDelay(80);
		PwmStop(WIFI_IOT_PWM_PORT_PWM1); //浇水小段时间就够
		GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 0);
		uart_buff[0] = '5'; //防止一直浇水
		printf("watering 500ms done\n");
	}
	else
	{
		printf("******* No water 1 *****\n");
		PwmStop(WIFI_IOT_PWM_PORT_PWM1);
	}

	if (mqtt_buff[0] == '4' && mqtt_buff[1] == '1')
	{
		//PwmStart(WIFI_IOT_PWM_PORT_PWM1, 30000, 40000);
		GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 1);
		osDelay(80);
		PwmStop(WIFI_IOT_PWM_PORT_PWM1); //浇水500ms就够
		GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_14, 0);
		mqtt_buff[0] = '5';
		printf("watering 500ms done\n");
	}
	else
	{
		printf("******* No Water 2 *****\n");
		PwmStop(WIFI_IOT_PWM_PORT_PWM1);
	}
}
void EnvironmentDetc(void)
{
	if (EnvData.ppm_val > 5000 || EnvData.temp_val > 80)
	{
		printf("******* Enviroment statues is INNORMAL. BEPP is Alarming *****\n");
		PwmStart(WIFI_IOT_PWM_PORT_PWM1, 30000, 40000);
		osDelay(200);
	}
	else
	{
		printf("******* No Alarm *****\n");
		PwmStop(WIFI_IOT_PWM_PORT_PWM1);
	}
}

/********************Water UnionDevices ************/
static void Water_Union(void)
{
	//UartRead(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE);
	hi_uart_read_timeout(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE, 10);
	printf("Uart1 read water data:%s \n", uart_buff_ptr);
	//fan
	if (uart_buff[0] == '1' && uart_buff[1] == '0')
	{
		uart_buff[0] = '5';
		strcpy(water_union_data,"turn off fan");
		printf("turn off fan \n");
		return;
	}
	if (uart_buff[0] == '1' && uart_buff[1] == '1')
	{
		uart_buff[0] = '5';
		strcpy(water_union_data,"turn on fan lev1");
		printf("turn on fan lev1 \n");
		return;
	}
	if (uart_buff[0] == '1' && uart_buff[1] == '2')
	{
		uart_buff[0] = '5';
		strcpy(water_union_data,"turn on fan lev2");
		printf("turn on fan lev2 \n");
		return;
	}
	if (uart_buff[0] == '1' && uart_buff[1] == '3')
	{
		uart_buff[0] = '5';
		strcpy(water_union_data,"turn on fan lev3");
		printf("turn on fan lev3 \n");
		return;
	}

	//door
	if (uart_buff[0] == '2' && uart_buff[1] == '1')
	{
		uart_buff[0] = '5';
		strcpy(water_union_data,"open door");
		printf("open door \n");
		return;
	}

	//lamb
	if (uart_buff[0] == '3' && uart_buff[1] == '0')
	{
		uart_buff[0] = '5';
		strcpy(water_union_data,"turn off lamb");
		printf("turn off lamb \n");
		return;
	}
	if (uart_buff[0] == '3' && uart_buff[1] == '1')
	{
		uart_buff[0] = '5';
		strcpy(water_union_data,"turn on lamb lev1");
		printf("turn on lamb lev1 \n");
		return;
	}
	if (uart_buff[0] == '3' && uart_buff[1] == '2')
	{
		uart_buff[0] = '5';
		strcpy(water_union_data,"turn on lamb lev2");
		printf("turn on lamb lev2 \n");
		return;
	}
	if (uart_buff[0] == '3' && uart_buff[1] == '3')
	{
		uart_buff[0] = '5';
		strcpy(water_union_data,"turn on lamb lev3");
		printf("turn on lamb lev3 \n");
		return;
	}

	//water
	if (uart_buff[0] == '4' && uart_buff[1] == '1')
	{
		uart_buff[0] = '5';
		strcpy(water_union_data,"go ahead water");
		printf("go ahead water \n");
		return;
	}

	return;
}

/******************** TASK *************************/
static void MQTT_FanTask(void)
{
	MyUartInit();
	FanInit();
	DoorInit();
	LambInit();
	WaterInit();
	WifiConnect("r1", "88888889");
	printf("Starting ...\n");
	int rc, count = 0;
	MQTTClient client;

	NetworkInit(&network);
	printf("NetworkConnect  ...\n");

begin:
	NetworkConnect(&network, "120.55.170.12", 1883); // hellokun.cn
	printf("MQTTClientInit  ...\n");
	MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));

	MQTTString clientId = MQTTString_initializer;
	clientId.cstring = "MRobot_uniondevices";

	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
	data.clientID = clientId;
	data.willFlag = 0;
	data.MQTTVersion = 3;
	data.keepAliveInterval = 0;
	data.cleansession = 1;

	printf("MQTTConnect  ...\n");
	rc = MQTTConnect(&client, &data);
	if (rc != 0)
	{
		printf("MQTTConnect: %d\n", rc);
		NetworkDisconnect(&network);
		MQTTDisconnect(&client);
		osDelay(200);
		goto begin;
	}

	printf("MQTTSubscribe  ...\n");
	//其他设备 web_fan_btn web_door_btn  web_water_btn
	rc = MQTTSubscribe(&client, "web_fan_btn", 2, messageArrived); //回调
	if (rc != 0)
	{
		printf("MQTTSubscribe: %d\n", rc);
		osDelay(200);
		goto begin;
	}

	rc = MQTTSubscribe(&client, "web_fan_btn", 2, messageArrived); //回调
	if (rc != 0)
	{
		printf("MQTTSubscribe: %d\n", rc);
		osDelay(200);
		goto begin;
	}

	rc = MQTTSubscribe(&client, "web_door_btn", 2, messageArrived); //回调
	if (rc != 0)
	{
		printf("MQTTSubscribe: %d\n", rc);
		osDelay(200);
		goto begin;
	}

	rc = MQTTSubscribe(&client, "web_lamb_btn", 2, messageArrived); //回调
	if (rc != 0)
	{
		printf("MQTTSubscribe: %d\n", rc);
		osDelay(200);
		goto begin;
	}

	rc = MQTTSubscribe(&client, "web_water_btn", 2, messageArrived); //回调
	if (rc != 0)
	{
		printf("MQTTSubscribe: %d\n", rc);
		osDelay(200);
		goto begin;
	}
	while (++count)
	{
		FanCtr();
		if (fan_status)
		{
			printf("******* Fan ON ********");
		}
		else
		{
			printf("******** Fan Off *********");
		}
		DoorCtr();
		LambCtr();
      

		AHT20_Calibrate();
		AHT20_StartMeasure();
		AHT20_GetMeasureResult(&EnvData.temp_val, &EnvData.humi_val);
		EnvData.ppm_val = Get_MQ2_PPM();
		printf("humity: %.2f\n", EnvData.humi_val);
		printf("temperture: %.2f\n", EnvData.temp_val);
		printf("mq2 ppm: %.2f\n", EnvData.ppm_val);
		EnvironmentDetc();
		WaterCtr(); //串口、mqtt数据控制
		Water_Union();

		MQTTMessage message_humi;
		char payload_humi[30];
		char payload_temp[30];
		char payload_ppm[30];

		message_humi.qos = 2;
		message_humi.retained = 0;
		message_humi.payload = payload_humi;
		sprintf(payload_humi, "humidity%.2f", EnvData.humi_val);
		message_humi.payloadlen = strlen(payload_humi);

		MQTTMessage message_temp;
		message_temp.qos = 2;
		message_temp.retained = 0;
		message_temp.payload = payload_temp;
		sprintf(payload_temp, "temperture%.2f", EnvData.temp_val);
		message_temp.payloadlen = strlen(payload_temp);

		MQTTMessage message_mq2;
		message_mq2.qos = 2;
		message_mq2.retained = 0;
		message_mq2.payload = payload_ppm;
		sprintf(payload_ppm, "mq2_ppm%.2f", EnvData.ppm_val);
		message_mq2.payloadlen = strlen(payload_ppm);

		MQTTMessage message;
		char payload[30];
		message.qos = 2;
		message.retained = 0;
		message.payload = payload;
		sprintf(payload, "message number %d", count);
		message.payloadlen = strlen(payload);

		char payload_water_union[30];	 //互联设备中转消息
		MQTTMessage message_water_union; //云端控制
		message_water_union.qos = 2;
		message_water_union.retained = 0;
		message_water_union.payload = payload_water_union;
		sprintf(payload_water_union, "%s", water_union_data);
		message_water_union.payloadlen = strlen(payload_water_union);

		if ((rc = MQTTPublish(&client, "water_humi", &message_humi)) != 0)
		{
			printf("Return code from MQTT publish is %d\n", rc);
			NetworkDisconnect(&network);
			MQTTDisconnect(&client);
			goto begin;
		}
		osDelay(20);
		if ((rc = MQTTPublish(&client, "water_temp", &message_temp)) != 0)
		{
			printf("Return code from MQTT publish is %d\n", rc);
			NetworkDisconnect(&network);
			MQTTDisconnect(&client);
			goto begin;
		}
		osDelay(20);
		if ((rc = MQTTPublish(&client, "water_mq2", &message_mq2)) != 0)
		{
			printf("Return code from MQTT publish is %d\n", rc);
			NetworkDisconnect(&network);
			MQTTDisconnect(&client);
			goto begin;
		}
		osDelay(20);
		if ((rc = MQTTPublish(&client, "water_union", &message_water_union)) != 0)
		{
			printf("Return code from MQTT publish is %d\n", rc);
			NetworkDisconnect(&network);
			MQTTDisconnect(&client);
			goto begin;
		}
       osDelay(10);
		printf("----- count = %d ------\r\n", count);
		if (count > 1000)
		{
			count = 1;
		}
		strcpy(water_union_data,"niubility");
	}
}
static void MQTT_Fan(void)
{
	osThreadAttr_t attr;

	attr.name = "MQTT_FanTask";
	attr.attr_bits = 0U;
	attr.cb_mem = NULL;
	attr.cb_size = 0U;
	attr.stack_mem = NULL;
	attr.stack_size = 10240;
	attr.priority = osPriorityNormal;

	if (osThreadNew((osThreadFunc_t)MQTT_FanTask, NULL, &attr) == NULL)
	{
		printf("[MQTT_Fan] Falied to create MQTT_FanTask!\n");
	}
}
APP_FEATURE_INIT(MQTT_Fan);